﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using dotNails.CodeGen.Models;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using dotNails.CodeGen.Util;
using System.Windows.Media.Animation;

namespace dotNails.UI {
	/// <summary>
	/// Interaction logic for ConnectionStringManager.xaml
	/// </summary>
	public partial class ConnectionStringManager : UserControl {
		public DbmlData DbmlData { get; set; }
		public event ConnectionStringSavedHandler ConnectionStringSaved;
		public delegate void ConnectionStringSavedHandler(object sender, dotNails.CodeGen.Models.DataBase dbmlDatabase);
		public string ConnectionString { get; set; }
		
		public ConnectionStringManager() {
			InitializeComponent();
		}

		void btnTest_Click(object sender, RoutedEventArgs e) {
			if (GetDbFromConnectionString(txtConnectionString.Text) != null) {
				DisplayTestResult("Connection succeeded", true);
			}
			else {
				DisplayTestResult("Connection failed", false);
			}
		}
		
		void btnSave_Click(object sender, RoutedEventArgs e) {
			try
			{
				Microsoft.SqlServer.Management.Smo.Database smoDb = GetDbFromConnectionString(txtConnectionString.Text);

				if (smoDb != null)
				{
					dotNails.CodeGen.Models.DataBase dbmlDatabase = new DataBase();
					dbmlDatabase.Class = DbmlData.Name + "DataContext";
					dbmlDatabase.Name = smoDb.Name;

					dbmlDatabase.Connection = new Connection();
					dbmlDatabase.Connection.ConnectionString = txtConnectionString.Text;
					dbmlDatabase.Connection.SettingsPropertyName = dbmlDatabase.Name + "ConnectionString";
					
					if (ConnectionStringSaved != null)
					{
						ConnectionStringSaved(this, dbmlDatabase);
						Visibility = Visibility.Collapsed;
					}
				}
				else
				{
					DisplayTestResult("Invalid connection string", false);
				}
			}
			catch (Exception ex)
			{
				LogUtil.EventLogMessage(ex.Message, ex.InnerException, ex.StackTrace);
			}
		}

		void btnCancel_Click(object sender, RoutedEventArgs e) {
			Visibility = Visibility.Collapsed;
		}

		private Microsoft.SqlServer.Management.Smo.Database GetDbFromConnectionString(string connectionString) {
			Microsoft.SqlServer.Management.Smo.Database smoDb = null;
			try {
				SqlConnection conn = new SqlConnection(connectionString);
				Server server = new Server(new ServerConnection(conn));

				string initialCatalog = GetInitialCatalogFromConnectionString(connectionString);

				// Use "Initial Catalog" in the connection string to get the correct db
				if (server != null) {
					foreach (Microsoft.SqlServer.Management.Smo.Database db in server.Databases) {
						if (db.Name == initialCatalog) {
							smoDb = db;
							break;
						}
					}
				}
			}
			catch (Exception e) {
				smoDb = null;
			}

			return smoDb;
		}

		private string GetInitialCatalogFromConnectionString(string connectionString) {
			string initialCatalog = string.Empty;

			try
			{
				int index = connectionString.IndexOf("Initial Catalog=", StringComparison.OrdinalIgnoreCase);
				if (index >= 0)
				{
					index = index + 16; // advance to end of =
					int nextSemicolon = connectionString.IndexOf(";", index);
					initialCatalog = connectionString.Substring(index, nextSemicolon - index);
				}
			}
			catch (Exception ex)
			{
				LogUtil.EventLogMessage(ex.Message, ex.InnerException, ex.StackTrace);
			}

			return initialCatalog;
		}

		private void DisplayTestResult(string output, bool succeeded) {
			TestResult.Text = output;
			TestResult.Opacity = 1.0;
			if (succeeded) {
				TestResult.Foreground = new SolidColorBrush(Color.FromArgb(0xFF, 0x33, 0xCC, 0x33));
			}
			else {
				TestResult.Foreground = new SolidColorBrush(Color.FromArgb(0xFF, 0xCC, 0x33, 0x33));
			}
			TestResult.Visibility = Visibility.Visible;
			FadeOutTestResults();
		}

		private void FadeOutTestResults() {
			// Fade out the test results
			// Create a storyboard to contain the animations.
			Storyboard storyboard = new Storyboard();
			
			// Create a DoubleAnimation to fade the not selected option control
			DoubleAnimation animation = new DoubleAnimation();

			animation.From = 1.0;
			animation.To = 0.0;
			animation.Duration = new Duration(TimeSpan.FromSeconds(4));
			// Configure the animation to target the property Opacity
			Storyboard.SetTargetName(animation, TestResult.Name);
			Storyboard.SetTargetProperty(animation, new PropertyPath(Control.OpacityProperty));
			// Add the animation to the storyboard
			storyboard.Children.Add(animation);

			// Begin the storyboard
			storyboard.Begin(this);
		}
	}
}
